package com.base.cn.platform.os.statistics;

import com.base.cn.platform.os.common.utils.DateUtils;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.result.ResultUtil;
import com.base.cn.platform.os.service.manage.statistics.goods.ZStatisticsGoodsPVCountService;
import com.base.cn.platform.os.service.manage.statistics.goods.ZStatisticsGoodsUVCountService;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 商品UV日志统计工具
 *
 * @author s.li
 * @date 2019/04/24
 */
@Slf4j
public class GoodsUVStatisticsUtils {
    private static Gson gson =new Gson();
    /**
     * 商品UV 数据统计
     */
    public static void goodsPVUVStatistics(ZStatisticsGoodsUVCountService zStatisticsGoodsUVCountService,
                                           ZStatisticsGoodsPVCountService zStatisticsGoodsPVCountService){
        try {
            File classPathDir = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX);
            File logsFileDir = new File(classPathDir,"/static/logs/goods");
            if(logsFileDir.exists()){
                String[] fileNameArr = logsFileDir.list();
                List<String> fileNameList = new ArrayList<>();
                if(ObjectUtils.isNotEmpty(fileNameArr)){
                    String exFileName = "goods-uv-"+ DateUtils.format(new Date(),"yyyy-MM-dd")+".log";
                    List<String> logFileLineContextList = LogFileUtils.getLogFileLineContextList(logsFileDir,fileNameList,fileNameArr,exFileName);

                    //处理日志文件内容(UV)
                    List<Map<String,Object>> uvDataList = handleGoodsUVLogsContext(logFileLineContextList);
                    //处理日志文件内容(PV)
                    List<Map<String,Object>> pvDataList = handleGoodsPVLogsContext(logFileLineContextList);
                    if(ObjectUtils.isNotEmpty(uvDataList) && ObjectUtils.isNotEmpty(pvDataList)){
                        //生成UV
                        Map<String,Object> resultMap = zStatisticsGoodsUVCountService.genGoodsUVCountList(uvDataList);
                        if(ResultUtil.getSuccess(resultMap)){//生成PV
                            resultMap = zStatisticsGoodsPVCountService.genGoodsPVCountList(pvDataList);
                        }
                        //删除文件
                        LogFileUtils.deleteLogFile(resultMap,logsFileDir,fileNameList);
                    }
                }
            }
        } catch (Exception e) {
            log.error("goodsPVUVStatistics()--error",e);
        }
    }

    /**
     * 商品(UV)处理日志文件内容
     * @param logFileLineContextList 内容列表，第个元素是日志文件中一行
     * @return List<Map<String,Object>>
     */
    private static List<Map<String,Object>> handleGoodsUVLogsContext(List<String> logFileLineContextList){
        if(ObjectUtils.isNotEmpty(logFileLineContextList)){
            List<Map<String,String>> mapList = getMapDataList(logFileLineContextList,true);
            if(ObjectUtils.isNotEmpty(mapList)){
                Map<String,List<Map<String,String>>> stringListMap = mapList.stream().collect(Collectors.groupingBy(e->e.get("tenantId")));
                List<Map<String,String>> dataList = stringListMap.get("0");
                List<Map<String,Object>> uvDataList = new ArrayList<>();
                if(ObjectUtils.isNotEmpty(dataList)){
                    //以天分组
                    Map<String,List<Map<String,String>>> listMap = dataList.stream().collect(Collectors.groupingBy(e->e.get("time")));
                    listMap.forEach((k,list)->{
                        //以商品ID和类型为KEY，进行分组
                        Map<String,List<Map<String,String>>> goodsListMap = list.stream().collect(Collectors.groupingBy(e->e.get("goodsId")+"_"+e.get("goodsType")));
                        goodsListMap.forEach((key,goodsList)->{
                            Map<String,Object> map = new HashMap<>();
                            map.put("countTime", DateUtils.parseDate(k,"yyyy-MM-dd"));
                            String[] arr = key.split("_");
                            map.put("goodsId",arr[0]);
                            map.put("goodsType",arr[1]);
                            //再以IP分组，得到UV量
                            int uvCount = goodsList.stream().collect(Collectors.groupingBy(e->e.get("ipAddr"))).size();
                            map.put("uvCount", uvCount);
                            uvDataList.add(map);
                        });
                    });
                    return uvDataList;
                }
            }
        }
        return null;
    }

    /**
     * 商品(PV)处理日志文件内容
     * @param logFileLineContextList 内容列表，第个元素是日志文件中一行
     * @return List<Map<String,Object>>
     */
    private static List<Map<String,Object>> handleGoodsPVLogsContext(List<String> logFileLineContextList){
        if(ObjectUtils.isNotEmpty(logFileLineContextList)){
            List<Map<String,String>> mapList = getMapDataList(logFileLineContextList,false);
            if(ObjectUtils.isNotEmpty(mapList)){
                Map<String,List<Map<String,String>>> stringListMap = mapList.stream().collect(Collectors.groupingBy(e->e.get("tenantId")));
                List<Map<String,String>> dataList = stringListMap.get("0");
                List<Map<String,Object>> pvDataList = new ArrayList<>();
                if(ObjectUtils.isNotEmpty(dataList)){
                    //以小时分组
                    Map<String,List<Map<String,String>>> listMap = dataList.stream().collect(Collectors.groupingBy(e->e.get("time")));

                    Map<String,Map<String,Object>> maps = new HashMap<>();
                    listMap.forEach((k,list)->{
                        String[] timeArr = k.split(" ");

                        Map<String,List<Map<String,String>>> goodsListMap = list.stream().collect(Collectors.groupingBy(e->e.get("goodsId")+"_"+e.get("goodsType")));
                        goodsListMap.forEach((key,goodsList)->{
                            String _key = timeArr[0]+"_"+key;
                            Map<String,Object> map = maps.get(_key);
                            TreeMap<String,Integer> pvInfoMap = getPVInfoData(goodsList);
                            if(map==null){
                                map = new HashMap<>();
                                map.put("countTime", DateUtils.parseDate(timeArr[0],"yyyy-MM-dd"));
                                String[] arr = key.split("_");
                                map.put("goodsId",arr[0]);
                                map.put("goodsType",arr[1]);
                                map.put("pvCount", goodsList.size());
                                map.put("pvInfo", pvInfoMap);
                                maps.put(_key,map);
                            }else{
                                int pvCount = (int)map.get("pvCount");
                                TreeMap<String,Integer> _pvInfoMap = (TreeMap<String,Integer>)map.get("pvInfo");
                                map.put("pvCount",pvCount + goodsList.size());
                                _pvInfoMap.forEach((h,v)->{
                                    pvInfoMap.put(h,pvInfoMap.get(h)+v);
                                });
                                map.put("pvInfo",pvInfoMap);
                            }
                        });
                    });
                    if(ObjectUtils.isNotEmpty(maps)){
                        maps.forEach((k,v)->{
                            Map<String,Object> map = v;
                            TreeMap<String,Integer> pvInfo = (TreeMap<String,Integer>)v.get("pvInfo");
                            map.put("pvInfo",gson.toJson(pvInfo));
                            pvDataList.add(map);
                        });
                    }
                    return pvDataList;
                }
            }
        }
        return null;
    }

    /**
     * 获取PV明细
     * @param goodsList 某一天的PV数据列表
     * @return TreeMap<String,Integer>
     */
    private static TreeMap<String,Integer> getPVInfoData(List<Map<String,String>> goodsList){
        //以小时进行分组
        Map<String,List<Map<String,String>>> hMap = goodsList.stream().collect(Collectors.groupingBy(e->e.get("time").split(" ")[1]));
        TreeMap<String,Integer> infoMap = new TreeMap<>();
        IntStream.range(0,24).forEach(index->{
            String key;
            if(index < 10){
                key = "0"+index;
            }else{
                key = ""+index;
            }
            List<Map<String,String>> list = hMap.get(key);
            if(list !=null){
                infoMap.put(key,list.size());
            }else{
                infoMap.put(key,0);
            }
        });
        return infoMap;
    }

    /**
     * 获取日志数据
     * @param logFileLineContextList
     * @return
     */
    private static List<Map<String,String>> getMapDataList(List<String> logFileLineContextList,boolean isUV){
        List<Map<String,String>> mapList = new ArrayList<>();
        logFileLineContextList.forEach(lineContext->{
            String[] arr = lineContext.split("\\|");
            String ipAddr = arr[0];
            String time = arr[1];
            String goodsId = arr[2];
            String goodsType = arr[3];
            String tenantId = arr[4];
            Map<String,String> map = new HashMap<>();
            map.put("ipAddr",ipAddr);
            if(isUV){
                map.put("time",time.split(" ")[0]);//只取到天部分的时间
            }else{
                map.put("time",time.split(":")[0]);//只取到小时部分的时间
            }
            map.put("goodsId",goodsId);//商品ID
            map.put("goodsType",goodsType);//商品类型
            map.put("tenantId",tenantId);
            mapList.add(map);
        });
        return mapList;
    }
}
